home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / progut~1 / stdwin.zoo / alfa / bind.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-18  |  6.7 KB  |  368 lines

  1. /* TERMCAP STDWIN -- KEY BINDING. */
  2.  
  3. /* Separated from the default tables; the application may override
  4.    the tables but not the executable code. */
  5.  
  6. #ifdef unix
  7. #define DO_SGTTY
  8. #define DO_TERMCAP
  9. #endif
  10.  
  11. #include "alfa.h"
  12.  
  13. #ifdef DO_SGTTY
  14. #include <sgtty.h>
  15. #endif
  16.  
  17. #ifdef DO_TERMCAP
  18. /* Termcap functions: */
  19. char *tgetstr();
  20. int tgetnum();
  21. bool tgetflag();
  22. #endif /* DO_TERMCAP */
  23.  
  24. static void charbinding(), tcbinding(), setbinding();
  25.  
  26. /* Get key definitions from tty settings. */
  27.  
  28. void
  29. getttykeydefs(fd)
  30.     int fd;
  31. {
  32. #ifdef DO_SGTTY
  33.     struct sgttyb gttybuf;
  34.     struct tchars tcharbuf;
  35.     
  36.     copydefaults();
  37.     
  38.     gtty(fd, >tybuf);
  39.     charbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE, gttybuf.sg_erase);
  40.     
  41.     ioctl(fd, TIOCGETC, (char *) &tcharbuf);
  42.     charbinding(SHORTCUT, 0, FIRST_CMD+WC_CANCEL, tcharbuf.t_intrc);
  43.  
  44. #ifdef TIOCGLTC
  45.     {
  46.         struct ltchars ltcharbuf;
  47.         
  48.         ioctl(fd, TIOCGLTC, (char *) <charbuf);
  49.         charbinding(SHORTCUT, 0, SUSPEND_PROC, ltcharbuf.t_suspc);
  50.         charbinding(SHORTCUT, 0, REDRAW_SCREEN, ltcharbuf.t_rprntc);
  51.         charbinding(SHORTCUT, 0, LITERAL_NEXT, ltcharbuf.t_lnextc);
  52.     }
  53. #endif /* TIOCGLTC */
  54. #endif /* DO_SGTTY */
  55. }
  56.  
  57. #ifdef DO_SGTTY
  58. static void
  59. charbinding(type, id, item, key)
  60.     int type;
  61.     int id, item;
  62.     int key;
  63. {
  64.     if (key != 0 && (key&0xff) != 0xff) {
  65.         char keys[2];
  66.         keys[0]= key;
  67.         keys[1]= EOS;
  68.         setbinding(&_wprimap[*keys & 0xff], type, id, item, keys);
  69.     }
  70. }
  71. #endif /* DO_SGTTY */
  72.  
  73. /* Get key definitions from termcap. */
  74.  
  75. void
  76. gettckeydefs()
  77. {
  78. #ifdef DO_TERMCAP
  79.     copydefaults();
  80.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE,    "kb");
  81.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_LEFT,    "kl");
  82.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_RIGHT,    "kr");
  83.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_UP,        "ku");
  84.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_DOWN,    "kd");
  85.     /*
  86.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_CLEAR,    "kC");
  87.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_HOME,    "kh");
  88.     tcbinding(SHORTCUT, 0, FIRST_CMD+WC_HOME_DOWN,    "kH");
  89.     */
  90. #endif /* DO_TERMCAP */
  91. }
  92.  
  93. #ifdef DO_TERMCAP
  94. static void
  95. tcbinding(type, id, item, capname)
  96.     int type;
  97.     int id, item;
  98.     char capname[2];    /* Termcap capability name, e.g. "k1" */
  99. {
  100.     char buf[100];
  101.     char *p= buf;
  102.     char *keys;
  103.     
  104.     keys= tgetstr(capname, &p);
  105.     if (keys != NULL)
  106.         setbinding(&_wprimap[*keys & 0xff], type, id, item, keys);
  107. }
  108. #endif /* DO_TERMCAP */
  109.  
  110. /* Bind a menu item to a meta-key.
  111.    As there are no meta-keys on standard Unix,
  112.    this is translated to ESC-key. */
  113.  
  114. void
  115. wsetmetakey(id, item, key)
  116.     int id, item;
  117.     char key;
  118. {
  119.     char buf[3];
  120.     
  121.     buf[0]= '\033'; /* ESC */
  122.     buf[1]= key;
  123.     buf[2]= EOS;
  124.     wsetshortcut(id, item, buf);
  125. }
  126.  
  127. /* Bind a menu item to a key sequence.
  128.    Note that this call is not part of the universal STDWIN interface,
  129.    only of the Unix interface for ASCII terminals. */
  130.  
  131. void
  132. wsetshortcut(id, item, keys)
  133.     int id, item;
  134.     char *keys;
  135. {
  136.     if (keys == NULL || *keys == EOS)
  137.         return; /* Can't bind empty string */
  138.     copydefaults();
  139.     setbinding(&_wprimap[*keys & 0xff], SHORTCUT, id, item, keys);
  140. }
  141.  
  142. static struct keymap *extendmap();
  143.  
  144. static int
  145. mapsize(map)
  146.     struct keymap *map;
  147. {
  148.     int size;
  149.     
  150.     if (map == NULL)
  151.         return 0;
  152.     for (size= 0; map[size].type != SENTINEL; ++size)
  153.         ;
  154.     return size+1;
  155. }
  156.  
  157. static void
  158. setbinding(map, type, id, item, keys)
  159.     struct keymap *map;
  160.     int type;
  161.     int id, item;
  162.     char *keys;
  163. {
  164.     if (keys[1] == EOS) {
  165.         map->key= *keys;
  166.         map->type= type;
  167.         map->id= id;
  168.         map->item= item;
  169.     }
  170.     else {
  171.         struct keymap *nmap;
  172.         if (map->type != SECONDARY) {
  173.             map->type= SECONDARY;
  174.             map->id= createmap();
  175.         }
  176.         for (nmap= _wsecmap[map->id];
  177.             nmap->type != SENTINEL; ++nmap) {
  178.             if (nmap->key == keys[1])
  179.                 break;
  180.         }
  181.         if (nmap->type == SENTINEL)
  182.             nmap= extendmap((int) map->id, keys[1]);
  183.         if (nmap != NULL)
  184.             setbinding(nmap, type, id, item, keys+1);
  185.     }
  186. }
  187.  
  188. static struct keymap *
  189. extendmap(imap, c)
  190.     int imap;
  191.     int c;
  192. {
  193.     L_DECLARE(size, map, struct keymap);
  194.     
  195.     if (imap == 0 || imap >= SECMAPSIZE || (map= _wsecmap[imap]) == NULL)
  196.         return NULL;
  197.     size= mapsize(map);
  198.     L_EXTEND(size, map, struct keymap, 1);
  199.     _wsecmap[imap]= map;
  200.     if (map == NULL)
  201.         return NULL;
  202.     map += size - 2;
  203.     map->type= ORDINARY;
  204.     map->key= c;
  205.     map[1].type= SENTINEL;
  206.     return map;
  207. }
  208.  
  209. static int
  210. createmap()
  211. {
  212.     L_DECLARE(size, map, struct keymap);
  213.     int i;
  214.     
  215.     L_EXTEND(size, map, struct keymap, 1);
  216.     if (map == NULL)
  217.         return 0;
  218.     map->type= SENTINEL;
  219.     for (i= 0; i < SECMAPSIZE && _wsecmap[i] != NULL; ++i)
  220.         ;
  221.     if (i >= SECMAPSIZE) { /* Overflow of _wsecmap array */
  222.         L_DEALLOC(size, map);
  223.         return 0;
  224.     }
  225.     else {
  226.         _wsecmap[i]= map;
  227.         return i;
  228.     }
  229. }
  230.  
  231. /* Copy existing secondary key maps to dynamic memory.
  232.    Note: don't copy map 0, which is a dummy to force a dead-end street. */
  233.  
  234. static
  235. copydefaults()
  236. {
  237.     static bool been_here= FALSE;
  238.     int i;
  239.     struct keymap *map;
  240.     
  241.     if (been_here)
  242.         return;
  243.     been_here= TRUE;
  244.     
  245.     for (i= 1; i < SECMAPSIZE; ++i) {
  246.         map= _wsecmap[i];
  247.         if (map != NULL) {
  248.             int size= mapsize(map);
  249.             struct keymap *nmap;
  250.             int k;
  251.             nmap= (struct keymap *) malloc(
  252.                 (size_t) (size * sizeof(struct keymap)));
  253.             if (nmap != NULL) {
  254.                 for (k= 0; k < size; ++k)
  255.                     nmap[k]= map[k];
  256.             }
  257.             _wsecmap[i]= nmap;
  258.         }
  259.     }
  260. }
  261.  
  262. /* Routines to get a nice description of a menu item's shortcuts.
  263.    TO DO: protect against buffer overflow; cache output so it
  264.    isn't called so often (i.e., twice for each drawitem call!). */
  265.  
  266. static char *
  267. charrepr(c)
  268.     int c;
  269. {
  270.     static char repr[10];
  271.  
  272.     switch (c) {
  273.  
  274.     case 033:
  275.         return "ESC";
  276.     
  277.     case '\r':
  278.         return "CR";
  279.     
  280.     case '\b':
  281.         return "BS";
  282.     
  283.     case '\t':
  284.         return "TAB";
  285.     
  286.     case 0177:
  287.         return "DEL";
  288.  
  289.     default:
  290.         if (c < ' ') {
  291.             repr[0]= '^';
  292.             repr[1]= c|'@';
  293.             repr[2]= '\0';
  294.         }
  295.         else if (c < 0177) {
  296.             repr[0]= c;
  297.             repr[1]= '\0';
  298.         }
  299.         else {
  300.             repr[0]= '\\';
  301.             repr[1]= '0' + (c>>6);
  302.             repr[2]= '0' + ((c>>3) & 07);
  303.             repr[3]= '0' + (c & 07);
  304.             repr[4]= '\0';
  305.         }
  306.         return repr;
  307.  
  308.     }
  309. }
  310.  
  311. static char *
  312. addrepr(cp, c)
  313.     char *cp;
  314.     int c;
  315. {
  316.     char *rp= charrepr(c);
  317.     
  318.     while (*rp != '\0')
  319.         *cp++ = *rp++;
  320.     return cp;
  321. }
  322.  
  323. static char *
  324. followmap(cp, map, id, item, stack, level)
  325.     char *cp;
  326.     struct keymap *map;
  327.     int id, item;
  328.     unsigned char *stack;
  329.     int level;
  330. {
  331.     if (map->type == SHORTCUT) {
  332.         if (map->id == id && map->item == item) {
  333.             int i;
  334.             for (i= 0; i < level; ++i) {
  335.                 cp= addrepr(cp, (int) stack[i]);
  336.                 *cp++ = '-';
  337.             }
  338.             cp= addrepr(cp, (int) map->key);
  339.             *cp++ = ',';
  340.             *cp++ = ' ';
  341.         }
  342.     }
  343.     else if (map->type == SECONDARY) {
  344.         stack[level]= map->key;
  345.         map= _wsecmap[map->id];
  346.         for (; map->type != SENTINEL; ++map)
  347.             cp= followmap(cp, map, id, item, stack, level+1);
  348.     }
  349.     return cp;
  350. }
  351.  
  352. void
  353. getbindings(buf, id, item)
  354.     char *buf;
  355.     int id;
  356.     int item;
  357. {
  358.     char *cp= buf;
  359.     unsigned char stack[50];
  360.     struct keymap *map;
  361.     
  362.     for (map= _wprimap; map < &_wprimap[256]; ++map)
  363.         cp= followmap(cp, map, id, item, stack, 0);
  364.     if (cp > buf)
  365.         cp -= 2;
  366.     *cp= EOS;
  367. }
  368.